# coding=utf-8
import hashlib
import inspect
import json
import pkgutil
import random
from typing import Optional

import global_var
from base.base import AppException
from base.http_base import HttpResp
from server_module import misc_logic

from utils import proto_util
import asyncio


def to_one_dict(key, lst):
	result = {}
	for obj in lst:
		result[obj[key]] = obj
	return result


def to_list_dict(key, lst):
	result = {}
	for obj in lst:
		if obj[key] not in result:
			result[obj[key]] = []
		result[obj[key]].append(obj)
	return result


async def send_dict(user_id, data_dict: dict, force_send=False):
	if force_send:
		from server_module.server import ConnMgr
		await ConnMgr.ins.send_data(user_id, json.dumps(data_dict))
	else:
		from server_module import handler
		handler.add_msg(user_id, data_dict)


async def send_data(user_id, type, func, data_dict: dict, force_send=False):
	data_dict = proto_util.to_json_dict(data_dict)
	data_dict["type"] = type
	data_dict["func"] = func
	await send_dict(user_id, data_dict, force_send)


async def close_user(user_id):
	from mgr.user_mgr import UserMgr
	from server_module.server import ConnMgr
	await ConnMgr.ins.close_conn(user_id)
	await UserMgr.ins.remove_user(user_id)


async def raise_exception(user_id, msg):
	await misc_logic.send_tip(user_id, msg, True)
	raise AppException(HttpResp.FAILED, msg=msg)


def is_empty(obj):
	if obj is None:
		return True
	if type(obj) is str and obj == "":
		return True
	if type(obj) is list and len(obj) == 0:
		return True
	return False


def is_equal(a, b):
	if a == b:
		return True
	if str(a) == str(b):
		return True
	return False


async def sort(lst, key_func):
	"""异步排序人员列表。"""
	# 获取所有的排序值
	sort_values = await asyncio.gather(*(key_func(data) for data in lst))
	
	# 将人员与其对应的排序值结合，并按排序值排序
	sorted_lst = [data for _, data in sorted(zip(sort_values, lst), key=lambda t_data: t_data[0])]
	return sorted_lst


def get_num_at_index(s: str, index: int, normal=None) -> Optional[int]:
	if index < len(s):
		s_data = list(s)
		return int(s_data[index])
	return normal


def get_flag_str(s: str, index: int, value, s_len: int) -> Optional[str]:
	result = s
	
	for i in range(len(s), s_len):
		result += "0"
	result_list = list(result)
	result_list[index] = str(value)
	return "".join(result_list)


async def get_module_and_tip(module_name, user_id, err_msg):
	try:
		return __import__(module_name, globals=globals(), locals=locals(), fromlist=["src"])
	except:
		await raise_exception(user_id, err_msg)


def get_all_modules(package, fromlist=None):
	modules = []
	if fromlist is None:
		fromlist = ["src"]
	for importer, modname, ispkg in pkgutil.walk_packages(package.__path__, package.__name__ + '.'):
		modules.append(__import__(modname, globals=globals(), locals=locals(), fromlist=fromlist))
		if ispkg:  # 如果是子包
			modules.extend(get_all_modules(importer.find_module(modname).load_module(modname), fromlist))
	return modules


# 同步逻辑跑异步函数
def run_async(func, *args, **kwargs):
	loop = asyncio.get_event_loop()
	if loop.is_running():
		# 使用 run_in_executor 运行异步函数
		return loop.run_in_executor(None, lambda: loop.run_until_complete(func(*args, **kwargs)))
	else:
		return loop.run_until_complete(func(*args, **kwargs))


# 异步函数跑长时间执行的同步逻辑,避免同步函数卡死整个进程
async def run_sync(func, *args):
	loop = asyncio.get_event_loop()
	return await loop.run_in_executor(None, func, *args)
